1   /*
2    * Copyright (C) 2011 The Guava Authors
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package com.google.common.base;
18  
19  import static com.google.common.truth.Truth.assertThat;
20  
21  import com.google.common.annotations.GwtCompatible;
22  import com.google.common.collect.FluentIterable;
23  import com.google.common.collect.ImmutableList;
24  
25  import junit.framework.TestCase;
26  
27  import java.util.Collections;
28  import java.util.List;
29  import java.util.Set;
30  
31  /**
32   * Unit test for {@link Optional}.
33   *
34   * @author Kurt Alfred Kluever
35   */
36  @GwtCompatible(emulated = true)
37  public final class OptionalTest extends TestCase {
38    public void testAbsent() {
39      Optional<String> optionalName = Optional.absent();
40      assertFalse(optionalName.isPresent());
41    }
42  
43    public void testOf() {
44      assertEquals("training", Optional.of("training").get());
45    }
46  
47    public void testOf_null() {
48      try {
49        Optional.of(null);
50        fail();
51      } catch (NullPointerException expected) {
52      }
53    }
54  
55    public void testFromNullable() {
56      Optional<String> optionalName = Optional.fromNullable("bob");
57      assertEquals("bob", optionalName.get());
58    }
59  
60    public void testFromNullable_null() {
61      // not promised by spec, but easier to test
62      assertSame(Optional.absent(), Optional.fromNullable(null));
63    }
64  
65    public void testIsPresent_no() {
66      assertFalse(Optional.absent().isPresent());
67    }
68  
69    public void testIsPresent_yes() {
70      assertTrue(Optional.of("training").isPresent());
71    }
72  
73    public void testGet_absent() {
74      Optional<String> optional = Optional.absent();
75      try {
76        optional.get();
77        fail();
78      } catch (IllegalStateException expected) {
79      }
80    }
81  
82    public void testGet_present() {
83      assertEquals("training", Optional.of("training").get());
84    }
85  
86    public void testOr_T_present() {
87      assertEquals("a", Optional.of("a").or("default"));
88    }
89  
90    public void testOr_T_absent() {
91      assertEquals("default", Optional.absent().or("default"));
92    }
93  
94    public void testOr_supplier_present() {
95      assertEquals("a", Optional.of("a").or(Suppliers.ofInstance("fallback")));
96    }
97  
98    public void testOr_supplier_absent() {
99      assertEquals("fallback", Optional.absent().or(Suppliers.ofInstance("fallback")));
100   }
101 
102   public void testOr_nullSupplier_absent() {
103     Supplier<Object> nullSupplier = Suppliers.ofInstance(null);
104     Optional<Object> absentOptional = Optional.absent();
105     try {
106       absentOptional.or(nullSupplier);
107       fail();
108     } catch (NullPointerException expected) {
109     }
110   }
111 
112   public void testOr_nullSupplier_present() {
113     Supplier<String> nullSupplier = Suppliers.ofInstance(null);
114     assertEquals("a", Optional.of("a").or(nullSupplier));
115   }
116 
117   public void testOr_Optional_present() {
118     assertEquals(Optional.of("a"), Optional.of("a").or(Optional.of("fallback")));
119   }
120 
121   public void testOr_Optional_absent() {
122     assertEquals(Optional.of("fallback"), Optional.absent().or(Optional.of("fallback")));
123   }
124 
125   public void testOrNull_present() {
126     assertEquals("a", Optional.of("a").orNull());
127   }
128 
129   public void testOrNull_absent() {
130     assertNull(Optional.absent().orNull());
131   }
132 
133   public void testAsSet_present() {
134     Set<String> expected = Collections.singleton("a");
135     assertEquals(expected, Optional.of("a").asSet());
136   }
137 
138   public void testAsSet_absent() {
139     assertTrue("Returned set should be empty", Optional.absent().asSet().isEmpty());
140   }
141 
142   public void testAsSet_presentIsImmutable() {
143     Set<String> presentAsSet = Optional.of("a").asSet();
144     try {
145       presentAsSet.add("b");
146       fail();
147     } catch (UnsupportedOperationException expected) {
148     }
149   }
150 
151   public void testAsSet_absentIsImmutable() {
152     Set<Object> absentAsSet = Optional.absent().asSet();
153     try {
154       absentAsSet.add("foo");
155       fail();
156     } catch (UnsupportedOperationException expected) {
157     }
158   }
159 
160   public void testTransform_absent() {
161     assertEquals(Optional.absent(), Optional.absent().transform(Functions.identity()));
162     assertEquals(Optional.absent(), Optional.absent().transform(Functions.toStringFunction()));
163   }
164 
165   public void testTransform_presentIdentity() {
166     assertEquals(Optional.of("a"), Optional.of("a").transform(Functions.identity()));
167   }
168 
169   public void testTransform_presentToString() {
170     assertEquals(Optional.of("42"), Optional.of(42).transform(Functions.toStringFunction()));
171   }
172 
173   public void testTransform_present_functionReturnsNull() {
174     try {
175       Optional.of("a").transform(
176           new Function<String, String>() {
177             @Override public String apply(String input) {
178               return null;
179             }
180           });
181       fail("Should throw if Function returns null.");
182     } catch (NullPointerException expected) {
183     }
184   }
185 
186   public void testTransform_abssent_functionReturnsNull() {
187     assertEquals(Optional.absent(),
188         Optional.absent().transform(
189           new Function<Object, Object>() {
190             @Override public Object apply(Object input) {
191               return null;
192             }
193           }));
194   }
195 
196   // TODO(kevinb): use EqualsTester
197 
198   public void testEqualsAndHashCode_absent() {
199     assertEquals(Optional.<String>absent(), Optional.<Integer>absent());
200     assertEquals(Optional.absent().hashCode(), Optional.absent().hashCode());
201   }
202 
203   public void testEqualsAndHashCode_present() {
204     assertEquals(Optional.of("training"), Optional.of("training"));
205     assertFalse(Optional.of("a").equals(Optional.of("b")));
206     assertFalse(Optional.of("a").equals(Optional.absent()));
207     assertEquals(Optional.of("training").hashCode(), Optional.of("training").hashCode());
208   }
209 
210   public void testToString_absent() {
211     assertEquals("Optional.absent()", Optional.absent().toString());
212   }
213 
214   public void testToString_present() {
215     assertEquals("Optional.of(training)", Optional.of("training").toString());
216   }
217 
218   public void testPresentInstances_allPresent() {
219     List<Optional<String>> optionals =
220         ImmutableList.of(Optional.of("a"), Optional.of("b"), Optional.of("c"));
221     assertThat(Optional.presentInstances(optionals)).iteratesAs("a", "b", "c");
222   }
223 
224   public void testPresentInstances_allAbsent() {
225     List<Optional<Object>> optionals =
226         ImmutableList.of(Optional.absent(), Optional.absent());
227     assertThat(Optional.presentInstances(optionals)).isEmpty();
228   }
229 
230   public void testPresentInstances_somePresent() {
231     List<Optional<String>> optionals =
232         ImmutableList.of(Optional.of("a"), Optional.<String>absent(), Optional.of("c"));
233     assertThat(Optional.presentInstances(optionals)).iteratesAs("a", "c");
234   }
235 
236   public void testPresentInstances_callingIteratorTwice() {
237     List<Optional<String>> optionals =
238         ImmutableList.of(Optional.of("a"), Optional.<String>absent(), Optional.of("c"));
239     Iterable<String> onlyPresent = Optional.presentInstances(optionals);
240     assertThat(onlyPresent).iteratesAs("a", "c");
241     assertThat(onlyPresent).iteratesAs("a", "c");
242   }
243 
244   public void testPresentInstances_wildcards() {
245     List<Optional<? extends Number>> optionals =
246         ImmutableList.<Optional<? extends Number>>of(Optional.<Double>absent(), Optional.of(2));
247     Iterable<Number> onlyPresent = Optional.presentInstances(optionals);
248     assertThat(onlyPresent).iteratesAs(2);
249   }
250 
251   private static Optional<Integer> getSomeOptionalInt() {
252     return Optional.of(1);
253   }
254 
255   private static FluentIterable<? extends Number> getSomeNumbers() {
256     return FluentIterable.from(ImmutableList.<Number>of());
257   }
258 
259   /*
260    * The following tests demonstrate the shortcomings of or() and test that the casting workaround
261    * mentioned in the method Javadoc does in fact compile.
262    */
263 
264   @SuppressWarnings("unused") // compilation test
265   public void testSampleCodeError1() {
266     Optional<Integer> optionalInt = getSomeOptionalInt();
267     // Number value = optionalInt.or(0.5); // error
268   }
269 
270   @SuppressWarnings("unused") // compilation test
271   public void testSampleCodeError2() {
272     FluentIterable<? extends Number> numbers = getSomeNumbers();
273     Optional<? extends Number> first = numbers.first();
274     // Number value = first.or(0.5); // error
275   }
276 
277   @SuppressWarnings("unused") // compilation test
278   public void testSampleCodeFine1() {
279     Optional<Number> optionalInt = Optional.of((Number) 1);
280     Number value = optionalInt.or(0.5); // fine
281   }
282 
283   @SuppressWarnings("unused") // compilation test
284   public void testSampleCodeFine2() {
285     FluentIterable<? extends Number> numbers = getSomeNumbers();
286 
287     // Sadly, the following is what users will have to do in some circumstances.
288 
289     @SuppressWarnings("unchecked") // safe covariant cast
290     Optional<Number> first = (Optional) numbers.first();
291     Number value = first.or(0.5); // fine
292   }
293 }
294